﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit;
using NUnit.Framework;
using EventbriteService;
using EventbriteService.Factory;


namespace ClientTests
{
    [TestFixture]
    public class FactoryTests
    {
        [Test]
        public void CanCreateFactoryWithAssemblyFilter()
        {
            var factory = new EventbriteFactory<ITestObject>();
            Assert.IsNotNull(factory);
            Assert.IsInstanceOf<IEventbriteFactory<ITestObject>>(factory);
        }

        [Test]
        public void CanCreateFactoryWithDefaultFilter()
        {
            var factory = new EventbriteFactory<IUrlBuilder>();
            Assert.IsNotNull(factory);
            Assert.IsInstanceOf<IEventbriteFactory<IUrlBuilder>>(factory);
        }

        [Test]
        public void CanCreateInstanceOfRequestedType()
        {
            var factory = new EventbriteFactory<ITestObject>();
            var createdObject = factory.GetInstance();
            Assert.IsNotNull(createdObject);
            Assert.IsInstanceOf<TestObject>(createdObject);
        }

        [Test]
        public void CanCreateInstanceOfRequestedTypeWithConstructorParameter()
        {
            var factory = new EventbriteFactory<ITestObject>();
            var createdObject = factory.GetInstance(new[] { "Bolo" });
            Assert.IsNotNull(createdObject);
            Assert.IsInstanceOf<TestObject>(createdObject);
            Assert.IsTrue(createdObject.PropOne == "Bolo");
        }

        [Test]
        public void CanCreateInstanceOfRequestedTypeWithConstructorParameters()
        {
            var factory = new EventbriteFactory<ITestObject>();
            var createdObject = factory.GetInstance(new object[] { "Bolo", 2 });
            Assert.IsNotNull(createdObject);
            Assert.IsInstanceOf<TestObject>(createdObject);
            Assert.IsTrue(createdObject.PropOne == "Bolo");
            Assert.IsTrue(createdObject.PropTwo == 2);
        }

        [Test]
        public void CanCreateNamedInstancesOfRequestedType()
        {
            var factory = new EventbriteFactory<ITestMultipleObjects>();
            var objectOne = factory.GetInstance("one", new object[] { "One", 1 });
            var objectTwo = factory.GetInstance("two", new object[] { "Two", 2 });
            var objectThree = factory.GetInstance("three", new object[] { "Three", 3 });

            Assert.IsInstanceOf<TestObjectOne>(objectOne);
            Assert.IsTrue(objectOne.PropOne == "One" && objectOne.PropTwo == 1);

            Assert.IsInstanceOf<TestObjectTwo>(objectTwo);
            Assert.IsTrue(objectTwo.PropOne == "Two" && objectTwo.PropTwo == 2);

            Assert.IsInstanceOf<TestObjectThree>(objectThree);
            Assert.IsTrue(objectThree.PropOne == "Three" && objectThree.PropTwo == 3);
        }

        [Test]
        public void CanCreateInstanceOfMultipleConcreteTypes()
        {
            var factory = new EventbriteFactory<ITestMultipleObjects>();
            var createdObject = factory.GetInstance(new object[] { "just any of the requested types", 1 });

            var typeOfCreatedObject = createdObject.GetType();

            Assert.IsTrue(typeOfCreatedObject == typeof(TestObjectOne) || typeOfCreatedObject == typeof(TestObjectTwo) || typeOfCreatedObject == typeof(TestObjectThree));
            Assert.IsTrue(createdObject.PropOne == "just any of the requested types" && createdObject.PropTwo == 1);

        }
    }

    public interface ITestMultipleObjects
    {
        string PropOne { get; set; }
        int PropTwo { get; set; }
    }

    public interface ITestObject
    {
        string PropOne { get; set; }
        int PropTwo { get; set; }
    }

    public class TestObject : ITestObject
    {
        public TestObject() { }
        public TestObject(string s)
        {
            PropOne = s;
        }

        public TestObject(string s, int i)
        {
            PropOne = s;
            PropTwo = i;
        }
        public int PropTwo { get; set; }
        public string PropOne
        {
            get;
            set;
        }
    }

    [CreateWithName("one")]
    public class TestObjectOne : ITestMultipleObjects
    {
        public TestObjectOne() { }
        public TestObjectOne(string s)
        {
            PropOne = s;
        }

        public TestObjectOne(string s, int i)
        {
            PropOne = s;
            PropTwo = i;
        }
        public int PropTwo { get; set; }
        public string PropOne
        {
            get;
            set;
        }
    }

    [CreateWithName("two")]
    public class TestObjectTwo : ITestMultipleObjects
    {
        public TestObjectTwo() { }
        public TestObjectTwo(string s)
        {
            PropOne = s;
        }

        public TestObjectTwo(string s, int i)
        {
            PropOne = s;
            PropTwo = i;
        }
        public int PropTwo { get; set; }
        public string PropOne
        {
            get;
            set;
        }
    }

    [CreateWithName("three")]
    public class TestObjectThree : ITestMultipleObjects
    {
        public TestObjectThree() { }
        public TestObjectThree(string s)
        {
            PropOne = s;
        }

        public TestObjectThree(string s, int i)
        {
            PropOne = s;
            PropTwo = i;
        }
        public int PropTwo { get; set; }
        public string PropOne
        {
            get;
            set;
        }
    }
}
